package whf.framework.lucene;

import java.util.ArrayList;
import java.util.List;

import whf.framework.entity.Entity;
import whf.framework.log.env.Environment;
import whf.framework.lucene.index.IndexManager;
import whf.framework.resource.thread.ThreadPool;
import whf.framework.resource.thread.UnTimeoutablePoolableThread;
import whf.framework.util.Utils;

/**
 * @author king
 * @create 2008-1-23 下午04:33:52
 * 
 */
public class IndexUtils {
	private final static int INDEX_TYPE_UPDATE = 1;
	private final static int INDEX_TYPE_CREATE = 2;
	private final static int INDEX_TYPE_REMOVE = 3;
	
	private static IndexUtils instance = new IndexUtils();
	
	private List<IndexItem<Entity>> indexItems = Utils.newArrayList();
	private IndexManager indexBuilder;
	private IndexThread thread = null;
	
	private IndexUtils() {
		this.thread = new IndexThread();
		ThreadPool.getDefaultInstance().addThread(thread);
		//
		this.indexBuilder = new IndexManager();
	}
	
	public static IndexUtils getInstance() {
		return instance;
	}
	
	public <T extends Entity> void createIndex(T entity) {
		if(Environment.isIndexIgnoredEntity(entity)) return;
		this.indexItems.add(new IndexItem<Entity>(entity, INDEX_TYPE_CREATE));
	}
	
	public <T extends Entity> void updateIndex(T entity) {
		if(Environment.isIndexIgnoredEntity(entity)) return;
		this.indexItems.add(new IndexItem<Entity>(entity, INDEX_TYPE_UPDATE));
	}
	
	public <T extends Entity> void removeIndex(T entity) {
		if(Environment.isIndexIgnoredEntity(entity)) return;
		this.indexItems.add(new IndexItem<Entity>(entity, INDEX_TYPE_REMOVE));
	}
	
	public <T extends Entity> void indexEntities(List<T> entities) {
		for(T entity: entities) {
			this.indexItems.add(new IndexItem<Entity>(entity, INDEX_TYPE_UPDATE));
		}
	}
	
	class IndexThread extends UnTimeoutablePoolableThread {
		public IndexThread() {
			super.setInterval(1000 * 10 * 1);
		}
		
		public void handle() throws Exception{
			if(indexItems.isEmpty()) return;
			try{
				List<Entity> createEntities = new ArrayList<Entity>();
				List<Entity> updateEntities = new ArrayList<Entity>();
				List<Entity> removeEntities = new ArrayList<Entity>();
				synchronized(indexItems) {
					for(IndexItem<? extends Entity> indexItem: indexItems) {
						if(indexItem.indexType == INDEX_TYPE_CREATE) {
							if(!createEntities.contains(indexItem.entity))
								createEntities.add(indexItem.entity);
						} else if(indexItem.indexType == INDEX_TYPE_UPDATE) {
							if(!updateEntities.contains(indexItem.entity))
								updateEntities.add(indexItem.entity);
						} else if(indexItem.indexType == INDEX_TYPE_REMOVE) {
							if(!removeEntities.contains(indexItem.entity))
								removeEntities.add(indexItem.entity);
						}
					}
					indexItems.clear();
				}
				try{
					if(!createEntities.isEmpty())
						indexBuilder.indexEntieies(createEntities);
				} catch(Exception e){
					log.error(this, e);
				}
				try{
					if(!updateEntities.isEmpty())
						indexBuilder.updateEntities(updateEntities);
				} catch(Exception e){
					log.error(this, e);
				}
				try{
					if(!removeEntities.isEmpty())
						indexBuilder.removeEntities(removeEntities);
				} catch(Exception e){
					log.error(this, e);
				}
				//
			} catch(Exception e){
				log.error(this, e);
			}
		}
	}
	
	class IndexItem<T extends Entity>{
		private T entity;
		private int indexType;
		
		IndexItem(T entity, int indexType) {
			this.entity = entity;
			this.indexType = indexType;
		}
	}
}
